package ihm;

import java.util.Date;
import java.util.Scanner;

import reservation.Admin;
import reservation.Serveur;
import reservation.Trajet;
import reservation.Transport;
import data.TypeTransport;
import data.TypeTransportHelper;
import data.Ville;
import data.VilleHelper;

public class InterfaceAdmin extends Interface {

	private Admin admin;

	public InterfaceAdmin(Admin a) {
		if (a == null)
			throw new IllegalArgumentException("Admin est null");
		admin = a;
	}

	@Override
	public void process(Command command) {
		switch (command.getCommandWord()) {
		case PRINT:
			this.print(command);
			break;
		case DELETE:
			this.delete(command);
			break;
		case ADD:
			this.add(command.getSecondWord());
			break;
		case ALTER:
			this.alter(command);
			break;
		case SAVE:
			// TODO ne sauvegarde pas !!
			admin.save();
			break;
		default:
			printHelp();
			break;
		}
	}

	/**
	 * Ajoute un objet au serveur selon le choix de l'utilisateur
	 * 
	 * @author Cyril GORRIRERI
	 */
	private void add(String type) {
		if ("trajet".equals(type)) {
			addTrajet();
		} else if ("transport".equals(type)) {
			addTransport();
		} else {
			System.out.println("Erreur: Type vide ou qui n'existe pas !");
		}
	}

	/**
	 * Ajoute un trajet en demandant les informations a l'admin
	 * 
	 * @author Cyril GORRIRERI
	 */
	private void addTransport() {
		Scanner in = new Scanner(System.in);
		TypeTransport typeTransport = TypeTransport.UNKNOWN;
		int capacite = 0;

		System.out.println("*** Ajouter un transport ***");

		do {
			System.out.println("Choisissez un type de transport: ");
			TypeTransportHelper.showAll();
			System.out.print(">> ");
			typeTransport = TypeTransportHelper.getTypeTransport(in.nextLine());
		} while (typeTransport == TypeTransport.UNKNOWN);
		do {
			System.out.println("Entrez une capacite (positive): ");
			capacite = recupererNum(in);
		} while (capacite <= 0);

		try {
			admin.add(new Transport(typeTransport, capacite));
		} catch (Exception e) {
			System.out.println("Erreur: L'ajout ne peut pas etre fait !!");
		}
	}

	/**
	 * Ajoute un trajet au serveur via une interface console
	 * 
	 * @author Cyril GORRIRERI
	 */
	private void addTrajet() {
		Scanner in = new Scanner(System.in);
		int transportID = -1;
		Transport transport;
		Ville[] villes = new Ville[2];
		Date date = new Date();

		System.out.println("*** Ajouter un trajet ***");

		/* numéro du Type de transport */
		do {
			System.out.println("Choisissez un n° de transport: ");
			Serveur.getInstance().listeTransports();
			transportID = recupererNum(in);
		} while (transportID < 0);
		transport = Serveur.getInstance().obtenirTransport(transportID);
		if (transport == null) {
			System.out.println("Erreur: Ce transport n'existe pas !");
			return;
		}

		villes = recupererVilles(in);

		recupereDateDepart(in, date);

		try {
			admin.add(new Trajet(villes[0], villes[1], date, transport));
		} catch (Exception e) {
			System.out.println("Erreur: L'ajout ne peut pas etre fait !!");
		}
	}

	/**
	 * Modifie un objet selon le choix entré dans la console la commande est du
	 * type: alter TYPE [NUM_ID]
	 * 
	 * @param command
	 *            La command de l'admin
	 * @param command
	 */
	private void alter(Command command) {
		String type = command.getSecondWord();
		if ("trajet".equals(type)) {
			if (command.hasThirdWord()) {
				alterTrajet(command.getThirdWord());
			} else {
				alterTrajetWithChoice();
			}
		} else if ("transport".equals(type)) {
			if (command.hasThirdWord()) {
				alterTransport(command.getThirdWord());
			} else {
				alterTransportWithChoice();
			}
		} else {
			System.out.println("Erreur: Type doit être trajet ou transport !");
		}
	}

	/**
	 * Modifie un trajet du serveur
	 * 
	 * @param idT
	 *            L'id du trajet à modifier
	 * @author Cyril GORRIERI
	 */
	private void alterTrajet(String idT) {
		Scanner in = new Scanner(System.in);
		int id = -1;
		// test si l'id est un numéro
		try {
			id = Integer.parseInt(idT);
		} catch (NumberFormatException e) {
			System.out.println("Erreur: L'id du trajet n'est pas numérique");
			return;
		}
		Trajet trajet = admin.obtenirTrajet(id);
		// Si on ne trouve pas le trajet
		if (trajet == null) {
			System.out.println("Erreur: Le trajet n'existe pas");
			return;
		}
		int value;
		do {
			System.out.println("Que voulez vous modifier ?\n\t[0] Type de transport\n\t[1] Ville départ\n\t[2] Ville arrivée\n\t[3] Date départ\n\t[AUTRE] Quitter");
			printChevrons();
			value = recupererNum(in);
			switch (value) {
			case 0: // type de transport
				/* numéro du Type de transport */
				int transportID = -1;
				do {
					System.out.println("Choisissez un n° de transport: ");
					admin.listeTransports();
					System.out.print(">> ");
					try {
						transportID = Integer.parseInt(in.nextLine());
					} catch (Exception e) {
						value = -1;
					}
				} while (transportID < 0);
				Transport transport = admin.obtenirTransport(transportID);
				if (transport == null) {
					System.out.println("Erreur: ce numéro de transport n'existe pas !");
				} else if (trajet.getBillet().size() > transport.getCapacite()) {
					System.out.println("Erreur: ce transport ne contient pas assez de place pour tout les clients !");
				} else {
					try {
						trajet.setTransport(transport);
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				break;
			case 1:
				/* Ville de départ */
				Ville start = Ville.UNKNOWN;
				do {
					System.out.println("Ville de départ (différente de la ville d'arrivée): ");
					start = recupererVille(in);
				} while (start == Ville.UNKNOWN || start == trajet.getArrivee());
				try {
					trajet.setDepart(start);
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				break;
			case 2:
				/* Ville de d'arrivée */
				Ville stop = Ville.UNKNOWN;
				do {
					System.out.println("Ville d'arrivée (différente de la ville de départ): ");
					stop = recupererVille(in);
				} while (stop == Ville.UNKNOWN || stop == trajet.getDepart());
				try {
					trajet.setArrivee(stop);
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				break;
			case 3:
				/* Date de départ */
				Date date = new Date();
				recupereDateDepart(in, date);
				try {
					trajet.setDate(date);
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				break;
			default:
				value = -1;
				break;
			}
		} while (value >= 0);
		try {
			admin.alter(trajet);
		} catch (Exception e) {
			System.out.println("Erreur: Le trajet n'a pas été mis à jour");
		}
	}

	/**
	 * Modifie un trajet du serveur via un choix dans une liste
	 * 
	 * @author Cyril GORRIERI
	 */
	private void alterTrajetWithChoice() {
		Scanner in = new Scanner(System.in);
		System.out.println("Choisissez le n° de trajet à modifier:");
		admin.listeTrajets();
		printChevrons();
		alterTrajet(in.nextLine());
	}

	/**
	 * Modifie un transport du serveur
	 * 
	 * @param idT
	 *            L'id du transport à supprimer
	 * @author Cyril GORRIERI
	 */
	private void alterTransport(String idT) {
		Scanner in = new Scanner(System.in);
		int id = -1;
		// test si l'id est un numéro
		try {
			id = Integer.parseInt(idT);
		} catch (NumberFormatException e) {
			System.out.println("Erreur: L'id du transport n'est pas numérique");
			return;
		}
		Transport transport = admin.obtenirTransport(id);
		// Si on ne trouve pas le trajet
		if (transport == null) {
			System.out.println("Erreur: Le transport n'existe pas");
			return;
		}
		int value;
		do {
			System.out.println("Que voulez vous modifier ?\n\t[0] Type de transport\n\t[1] Capacite\n\t[AUTRE] Quitter");
			value = recupererNum(in);
			switch (value) {
			case 0:
				TypeTransport typeTransport = TypeTransport.UNKNOWN;
				do {
					System.out.println("Choisissez un type de transport: ");
					TypeTransportHelper.showAll();
					printChevrons();
					typeTransport = TypeTransportHelper.getTypeTransport(in.nextLine());
				} while (typeTransport == TypeTransport.UNKNOWN);
				try {
					transport.setCategorie(typeTransport);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				break;
			case 1:
				/* Capacite */
				int capacite = -1;
				do {
					System.out.println("Entrez une capacite (positive): ");
					capacite = recupererNum(in);
				} while (capacite <= 0);
				try {
					transport.setCapacite(capacite);
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				break;
			default:
				value = -1;
				break;
			}
		} while (value >= 0);
		try {
			admin.alter(transport);
		} catch (Exception e) {
			System.out.println("Erreur: Le transport n'a pas été mis à jour");
		}
	}

	/**
	 * Modifie un transport du serveur via un choix dans une liste
	 * 
	 * @author Cyril GORRIERI
	 */
	private void alterTransportWithChoice() {
		Scanner in = new Scanner(System.in);
		System.out.println("Choisissez le n° de traansport à supprimer:");
		Serveur.getInstance().listeTransports();
		printChevrons();
		deleteTransport(in.nextLine());
	}

	/**
	 * Supprime un objet selon le choix entré dans la console la commande est du
	 * type: delete TYPE [NUM_ID]
	 * 
	 * @param command
	 *            La command de l'admin
	 * @author Cyril GORRIERI
	 * 
	 */
	private void delete(Command command) {
		String type = command.getSecondWord();
		if ("trajet".equals(type)) {
			if (command.hasThirdWord()) {
				deleteTrajet(command.getThirdWord());
			} else {
				deleteTrajetWithChoice();
			}
		} else if ("transport".equals(type)) {
			if (command.hasThirdWord()) {
				deleteTransport(command.getThirdWord());
			} else {
				deleteTransportWithChoice();
			}
		} else {
			System.out.println("Erreur: Type vide ou qui n'existe pas !");
		}
	}

	/**
	 * Supprime un trajet du serveur
	 * 
	 * @param idT
	 *            L'id du trajet à supprimer
	 * @author Cyril GORRIERI
	 */
	private void deleteTrajet(String idT) {
		int id = -1;
		// test si l'id est un numéro
		try {
			id = Integer.parseInt(idT);
		} catch (NumberFormatException e) {
			System.out.println("Erreur: L'id du trajet n'est pas numérique");
			return;
		}
		Trajet t = Serveur.getInstance().obtenirTrajet(id);
		// Si on ne trouve pas le trajet
		if (t == null) {
			System.out.println("Erreur: Le trajet n'existe pas");
			return;
		}
		// test la suppression
		try {
			admin.delete(t);
		} catch (Exception e) {
			System.out.println("Erreur: La suppression a échouée");
		}
	}

	/**
	 * Supprime un trajet du serveur via un choix dans une liste
	 * 
	 * @author Cyril GORRIERI
	 */
	private void deleteTrajetWithChoice() {
		Scanner in = new Scanner(System.in);
		System.out.println("Choisissez le n° de trajet à supprimer:");
		Serveur.getInstance().listeTrajets();
		printChevrons();
		deleteTrajet(in.nextLine());
	}

	/**
	 * Supprime un transport du serveur
	 * 
	 * @param idT
	 *            L'id du transport à supprimer
	 * @author Cyril GORRIERI
	 */
	private void deleteTransport(String idT) {
		int id = -1;
		// test si l'id est un numéro
		try {
			id = Integer.parseInt(idT);
		} catch (NumberFormatException e) {
			System.out.println("Erreur: L'id du transport n'est pas numérique");
			return;
		}
		Transport t = Serveur.getInstance().obtenirTransport(id);
		// Si on ne trouve pas le trajet
		if (t == null) {
			System.out.println("Erreur: Le transport n'existe pas");
			return;
		}
		// test la suppression
		try {
			admin.delete(t);
		} catch (Exception e) {
			System.out.println("Erreur: La suppression a échouée");
		}
	}

	/**
	 * Supprime un transport du serveur via un choix dans une liste
	 * 
	 * @author Cyril GORRIERI
	 */
	private void deleteTransportWithChoice() {
		Scanner in = new Scanner(System.in);
		System.out.println("Choisissez le n° de traansport à supprimer:");
		Serveur.getInstance().listeTransports();
		printChevrons();
		deleteTransport(in.nextLine());
	}

	@Override
	protected void goodBye() {
		System.out.println("## Fin de l'administration des données ##");
	}

	@Override
	protected void presentation() {
		System.out.println("********* Client d'administration *********");
		System.out.println("Tapez une commande ou 'help' pour l'aide.");
	}

	@Override
	protected void printHelp() {
		super.printHelp();
		System.out.println("- Ajouter: add [transport | trajet]");
		System.out.println("- Modifier: alter [transport | trajet] [ID]");
		System.out.println("- Supprimer: delete [transport | trajet] [ID]");
		System.out.println("- Enregistrer: save");
	}

	/**
	 * Recupère une ville
	 * @param in Le scanner
	 * @return Ville
	 */
	private Ville recupererVille(Scanner in) {
		VilleHelper.showAll();
		printChevrons();
		return VilleHelper.getVille(in.nextLine());
	}

	/**
	 * Retourne un tableau contenant la ville de départ et la ville d'arrivée
	 * 
	 * @param in
	 *            Le scanner
	 * @return
	 */
	private Ville[] recupererVilles(Scanner in) {
		Ville[] villes = new Ville[2];
		/* Ville de départ */
		do {
			System.out.println("Ville de départ: ");
			villes[0] = recupererVille(in);
		} while (villes[0] == Ville.UNKNOWN);

		/* Ville d'arrivée */
		do {
			System.out
					.println("Ville d'arrivée (différente de la ville de départ): ");
			villes[1] = recupererVille(in);
		} while (villes[1] == Ville.UNKNOWN || villes[1] == villes[0]);
		return villes;
	}

	/**
	 * Recupère la date de départ
	 * 
	 * @param in
	 *            Le scanner d'entrée
	 * @param date
	 *            La date
	 */
	private void recupereDateDepart(Scanner in, Date date) {
		boolean validDate = false;
		do {
			try {
				System.out.println("Date départ [dd/MM/yyyy HH:mm]: ");
				printChevrons();
				date = dateFormat.parse(in.nextLine().trim());
				validDate = true;
			} catch (Exception e) {
			}
		} while (!validDate);
	}
}
